/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package lpii.clases;

import java.io.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author
 */
public final class Administrador {

    private Empleado[] empleados;
    private Planilla planillaHoy;
    private int k;

    public Administrador() {
        empleados = new Empleado[200];
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        Calendar hoy = Calendar.getInstance();
        CargarEmpleados();

        File f = new File("Planillas/" + sdf.format(hoy.getTime()) + ".dat");
        if (f.exists()) {
            planillaHoy = CargarPlanilla(hoy);
        } else {
            planillaHoy = new Planilla(hoy);
        }
    }

    public void RegistrarEmpleado(String dni, String nombre, String apellidoPaterno, String apellidoMaterno, int tipoTrabajador) {
        Empleado empleado = BuscarEmpleado(dni);
        if (empleado == null) {
            empleado = new Empleado(dni, nombre, apellidoPaterno, apellidoMaterno, tipoTrabajador);
            empleados[k++] = empleado;
            EscribirEmpleados();
        }
    }

    public void CargarEmpleados() {
        FileReader fr;

        String dni;
        String nombre;
        String apellidoPaterno;
        String apellidoMaterno;
        int tipoTrabajador;
        boolean estaTrabajando;
        boolean estaDatosBloqueado;

        try {
            String nFile = "Empleados/Empleados.dat";
            File f = new File(nFile);
            if (f.exists()) {
                fr = new FileReader(nFile);
                BufferedReader br = new BufferedReader(fr);
                String linea;
                while ((linea = br.readLine()) != null) {
                    StringTokenizer t = new StringTokenizer(linea, ",");
                    dni = t.nextToken();
                    nombre = t.nextToken();
                    apellidoPaterno = t.nextToken();
                    apellidoMaterno = t.nextToken();
                    tipoTrabajador = Integer.parseInt(t.nextToken());
                    estaTrabajando = Boolean.parseBoolean(t.nextToken());
                    estaDatosBloqueado = Boolean.parseBoolean(t.nextToken());
                    empleados[k++] = new Empleado(dni, nombre, apellidoPaterno, apellidoMaterno, tipoTrabajador, estaTrabajando, estaDatosBloqueado);
                }
                br.close();
                fr.close();
            }
        } catch (IOException ex) {
            Logger.getLogger(Planilla.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void EscribirEmpleados() {
        try {
            FileWriter fw = new FileWriter("Empleados/Empleados.dat");
            PrintWriter pw = new PrintWriter(fw);

            for (int i = 0; i < k; i++) {
                pw.println(empleados[i].getDni() + "," + empleados[i].getNombre() + "," + empleados[i].getApellidoPaterno()
                        + "," + empleados[i].getApellidoMaterno() + "," + empleados[i].getTipoTrabajador()
                        + "," + empleados[i].isEstaTrabajando() + "," + empleados[i].isEstaDatosBloqueado());
            }
            pw.close();
            fw.close();
        } catch (IOException ex) {
            Logger.getLogger(Administrador.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public void EscribirPlanilla() {
        this.planillaHoy.EscribirPlanilla();
    }

    public Planilla CargarPlanilla(Calendar fecha) {
        Planilla p = null;
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        FileReader fr;
        try {
            String nFile = "Planillas/" + sdf.format(fecha.getTime()) + ".dat";
            File f = new File(nFile);
            if (f.exists()) {
                p = new Planilla(fecha);

                fr = new FileReader(nFile);
                BufferedReader br = new BufferedReader(fr);
                sdf = new SimpleDateFormat("HH:mm");
                String linea, dni, shi, shs;
                Calendar hi = Calendar.getInstance(), hs = Calendar.getInstance();
                while ((linea = br.readLine()) != null) {
                    StringTokenizer t = new StringTokenizer(linea, ",");
                    dni = t.nextToken();
                    shi = t.nextToken();
                    shs = t.nextToken();
                    try {
                        if (!shi.isEmpty() && !shs.isEmpty()) {
                            hi.setTime(sdf.parse(shi));
                            hs.setTime(sdf.parse(shs));
                            p.getDiaPagos()[k++] = new DiaPago(dni, hi, hs);
                        } else {
                            p.getDiaPagos()[k++] = new DiaPago(dni);
                        }
                    } catch (ParseException ex) {
                        Logger.getLogger(Planilla.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                br.close();
                fr.close();
            }
        } catch (IOException ex) {
            Logger.getLogger(Planilla.class.getName()).log(Level.SEVERE, null, ex);
        }
        return p;
    }

    public Empleado BuscarEmpleado(String dni) {
        for (int i = 0; i < k; i++) {
            if (empleados[i].getDni().equals(dni)) {
                return empleados[i];
            }
        }
        return null;
    }

    public int IndiceEmpleado(String dni) {
        for (int i = 0; i < k; i++) {
            if (empleados[i].getDni().equals(dni)) {
                return i;
            }
        }
        return -1;
    }

    public void ModificarDatosEmpleado(String dni, String nombre, String apellidoPaterno, String apellidoMaterno, int tipoTrabajador) {
        Empleado empleado = BuscarEmpleado(dni);
        if (empleado != null && !empleado.isEstaDatosBloqueado()) {
            empleado.setNombre(nombre);
            empleado.setApellidoPaterno(apellidoPaterno);
            empleado.setApellidoMaterno(apellidoMaterno);
            empleado.setTipoTrabajador(tipoTrabajador);
            EscribirEmpleados();
        } else {
            System.out.println("Datos bloqueados. No puede modificar");
        }
    }

    public void CambiarBloquearDatos(String dni, boolean estado) {
        Empleado empleado = BuscarEmpleado(dni);
        if (empleado != null) {
            empleado.setEstaDatosBloqueado(estado);
            EscribirEmpleados();
        }
    }

    public void CambiarEstadoTrabajo(String dni, boolean estado) {
        Empleado empleado = BuscarEmpleado(dni);
        if (empleado != null && !empleado.isEstaDatosBloqueado()) {
            empleado.setEstaTrabajando(estado);
            EscribirEmpleados();
        } else {
            System.out.println("Datos bloqueados. No puede modificar");
        }
    }

    public void EliminarEmpleado(String dni) {
        int i = IndiceEmpleado(dni);
        if (i != -1) {
            while (i + 1 < k) {
                empleados[i] = empleados[i + 1];
                i++;
            }
            k--;
            EscribirEmpleados();
        }
    }

    public void RegistrarHoraEntrada(String dni, Calendar hi) {
        Empleado empleado = BuscarEmpleado(dni);

        if (empleado != null && !empleado.isEstaDatosBloqueado()) {
            planillaHoy.getDiaPagos()[planillaHoy.getK()] = new DiaPago(dni, hi);
            planillaHoy.setK(planillaHoy.getK() + 1);
        } else {
            System.out.println("DNI. No registrado");
        }
    }

    public void RegistrarHoraSalida(String dni, Calendar hs) {
        Empleado empleado = BuscarEmpleado(dni);
        boolean marco = false;
        int j = -1;
        if (empleado != null && !empleado.isEstaDatosBloqueado()) {

            for (int i = 0; i < planillaHoy.getK(); i++) {
                if (planillaHoy.getDiaPagos()[i].getDniEmpleado().equals(dni) && planillaHoy.getDiaPagos()[i].getHoraIngreso() != null) {
                    planillaHoy.getDiaPagos()[i].setHoraSalida(hs);
                    marco = true;
                    j = i;
                    break;
                }
            }
            if (!marco && planillaHoy.getDiaPagos()[j].getHoraIngreso() != null) {
                System.out.println("No marco hora de entrada");
            }
        } else {
            System.out.println("DNI. No registrado");
        }
    }

    public void TerminarDia() {
        EscribirPlanilla();
    }

    public String ReporteEmpleado(String dni, Calendar fecha) {
        Planilla planilla;
        String cad = null;

        int faltas = 0, tardanzas = 0;
        double sueldo = 0.0, horasTrabajadas = 0;

        Empleado empleado = BuscarEmpleado(dni);

        if (empleado != null) {
            planilla = CargarPlanilla(fecha);
            if (planilla != null) {
                for (int i = 0; i < planilla.getK(); i++) {
                    if (planilla.getDiaPagos()[i].getDniEmpleado().equals(dni)) {

                        if (planilla.getDiaPagos()[i].getHoraIngreso() == null) {
                            faltas++;
                            horasTrabajadas = 0;
                        } else if (planilla.getDiaPagos()[i].getHoraIngreso().get(Calendar.HOUR_OF_DAY) > 9) {
                            tardanzas++;
                            horasTrabajadas = DiferenciaHoras(planilla.getDiaPagos()[i].getHoraIngreso(), planilla.getDiaPagos()[i].getHoraSalida());
                        }
                        sueldo = CalculaSueldo(empleado.getTipoTrabajador(), faltas, tardanzas, horasTrabajadas);
                        break;
                    }
                }
            }
            cad = empleado.toString() + "\t";
        }

        return cad;
    }

    public boolean EsBisiesto(int año) {
        if ((año % 400 == 0) || ((año % 4 == 0) && (año % 100 != 0))) {
            return true;
        }
        return false;
    }

    public boolean EsValida(Calendar fecha) {
        int dias[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (fecha.get(Calendar.MONTH) != 1) {
            if (fecha.get(Calendar.MONTH) != 1 && (fecha.get(Calendar.DATE) <= dias[fecha.get(Calendar.MONTH)])) {
                return true;
            } else if (fecha.get(Calendar.MONTH) != 1) {
                if (fecha.get(Calendar.DATE) < 29) {
                    return true;
                } else if (fecha.get(Calendar.DATE) == 29 && EsBisiesto(fecha.get(Calendar.YEAR))) {
                    return true;
                } else {
                    return false;
                }
            }
        }
        return false;
    }

    public String ReporteTardanzas() {
        Planilla planilla;
        String cad = "";
        File f;
        int tardanzas, horasTardanza;
        double monto;

        Calendar fecha, hoy = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy'");
        for (int i = 0; i < k; i++) {
            if (empleados[i].isEstaTrabajando()) {
                fecha = new GregorianCalendar(hoy.get(Calendar.YEAR), hoy.get(Calendar.MONTH), 1);
                f = new File("Planillas/" + sdf.format(fecha.getTime()) + ".dat");
                tardanzas = 0;
                horasTardanza = 0;
                while (EsValida(fecha) && f.exists()) {
                    planilla = CargarPlanilla(fecha);
                    for (int j = 0; j < planilla.getK(); j++) {
                        if (planilla.getDiaPagos()[i].getDniEmpleado().equals(empleados[i].getDni())) {
                            if (planilla.getDiaPagos()[i].getHoraIngreso() != null && planilla.getDiaPagos()[i].getHoraIngreso().get(Calendar.HOUR_OF_DAY) > 9) {
                                tardanzas++;
                                horasTardanza = planilla.getDiaPagos()[i].getHoraIngreso().get(Calendar.HOUR_OF_DAY) - 9;
                            }
                            break;
                        }
                    }
                    fecha.add(Calendar.DATE, 1);
                    f = new File("Planillas/" + sdf.format(fecha.getTime()) + ".dat");
                }

                monto = empleados[i].getSueldo() * (1 - empleados[i].HoraTardanza() * horasTardanza - empleados[i].HoraFalta() * (tardanzas / 4));
                cad += empleados[i].toString() + "\t" + tardanzas + "\t" + monto;
            } else {
                cad += empleados[i].toString() + "\tNo trabaja\n";
            }
        }
        return cad;
    }

    public String ReportePorDni(String dni) {
        Planilla planilla;
        String cad = "";

        int faltas = 0, tardanzas = 0;
        double sueldo = 0.0, horasTrabajadas = 0;
        File f;

        Empleado empleado = BuscarEmpleado(dni);
        Calendar hoy = Calendar.getInstance();
        Calendar fecha = new GregorianCalendar(hoy.get(Calendar.YEAR), hoy.get(Calendar.MONTH), 1);
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy'");

        if (empleado != null && empleado.isEstaTrabajando()) {
            f = new File("Planillas/" + sdf.format(fecha.getTime()) + ".dat");
            while (EsValida(fecha) && f.exists()) {
                planilla = CargarPlanilla(fecha);
                for (int i = 0; i < planilla.getK(); i++) {
                    if (planilla.getDiaPagos()[i].getDniEmpleado().equals(dni)) {

                        if (planilla.getDiaPagos()[i].getHoraIngreso() == null) {
                            faltas++;
                            horasTrabajadas = 0;
                        } else if (planilla.getDiaPagos()[i].getHoraIngreso().get(Calendar.HOUR_OF_DAY) > 9) {
                            tardanzas++;
                            horasTrabajadas = DiferenciaHoras(planilla.getDiaPagos()[i].getHoraIngreso(), planilla.getDiaPagos()[i].getHoraSalida());
                        }
                        break;
                    }
                }
                sueldo += sueldo = CalculaSueldo(empleado.getTipoTrabajador(), faltas, tardanzas, horasTrabajadas);

                fecha.add(Calendar.DATE, 1);
                f = new File("Plaillas/" + sdf.format(fecha.getTime()) + ".dat");
            }
            cad = empleado.toString() + "\t" + tardanzas + "\t" + faltas + "\t" + sueldo + "\n";
        }
        return cad;
    }

    public double DiferenciaHoras(Calendar hi, Calendar hs) {
        final long HOURS_PER_DAY = 60 * 60 * 1000;
        Date fi = new Date(hi.getTimeInMillis());
        Date fs = new Date(hs.getTimeInMillis());
        double diferencia = (fs.getTime() - fi.getTime()) / (1.0 * HOURS_PER_DAY);
        return diferencia;
    }

    public double CalculaSueldo(int tipo, int faltas, int tardanzas, double horasTrabajadas) {

        double sueldo = 0.0, horasAdicionales = 0.0;

        if (horasTrabajadas - 8 > 0) {
            horasAdicionales = horasTrabajadas - 8;
        }

        faltas += tardanzas / 4;
        tardanzas %= 4;

        switch (tipo) {
            case 1:
                sueldo = 5000 * (1 + 0.01 * horasAdicionales - 0.05 * faltas);
                break;
            case 2:
                sueldo = 12000 * (1 + 0.015 * horasAdicionales - 0.03 * faltas);
                break;
            case 3:
                sueldo = 2000 * (1 + 0.02 * horasAdicionales - 0.02 * faltas);
                break;
            case 4:
                sueldo = 600 * (1 + 0.015 * horasAdicionales - 0.02 * faltas);
                break;
        }
        return sueldo;
    }

    public void OrdenarEmpleadosPorTipo() {
        for (int i = 0; i < k - 1; i++) {
            int min = i;
            for (int j = i + 1; j < k; j++) {
                if (empleados[j].getTipoTrabajador() > empleados[min].getTipoTrabajador()) {
                    min = j;
                }
            }
            if (i != min) {
                Empleado aux = empleados[i];
                empleados[i] = empleados[min];
                empleados[min] = aux;
            }
        }
        EscribirEmpleados();        
    }
    
    
    
    public String ReporteEnOrden() {
        Planilla planilla;
        String cad = "";
        File f;
        int tardanzas, horasTardanza;
        double monto;

        Calendar fecha, hoy = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy'");
        OrdenarEmpleadosPorTipo();
        
        for (int i = 0; i < k; i++) {
            if (empleados[i].isEstaTrabajando()) {
                fecha = new GregorianCalendar(hoy.get(Calendar.YEAR), hoy.get(Calendar.MONTH), 1);
                f = new File("Planillas/" + sdf.format(fecha.getTime()) + ".dat");
                tardanzas = 0;
                horasTardanza = 0;
                while (EsValida(fecha) && f.exists()) {
                    planilla = CargarPlanilla(fecha);
                    for (int j = 0; j < planilla.getK(); j++) {
                        if (planilla.getDiaPagos()[i].getDniEmpleado().equals(empleados[i].getDni())) {
                            if (planilla.getDiaPagos()[i].getHoraIngreso() != null && planilla.getDiaPagos()[i].getHoraIngreso().get(Calendar.HOUR_OF_DAY) > 9) {
                                tardanzas++;
                                horasTardanza = planilla.getDiaPagos()[i].getHoraIngreso().get(Calendar.HOUR_OF_DAY) - 9;
                            }
                            break;
                        }
                    }
                    fecha.add(Calendar.DATE, 1);
                    f = new File("Planillas/" + sdf.format(fecha.getTime()) + ".dat");
                }

                monto = empleados[i].getSueldo() * (1 - empleados[i].HoraTardanza() * horasTardanza - empleados[i].HoraFalta() * (tardanzas / 4));
                cad += empleados[i].toString() + "\t" + monto;
            } else {
                cad += empleados[i].toString() + "\tNo trabaja\n";
            }
        }
        return cad;
    }
}
